import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import n4j.call_tree as ct
import math
import yinlichili.yuchuli as yuc


def loss_function(map, join_node):
    join_edge = []
    join_edge_length = []
    join_node_cood = []
    # 计算所有边长
    for i in range(len(join_node)):
        join_node_cood.append(map.virzuobiao[join_node[i]])
        for j in range(len(join_node) - i - 1):
            if map.map[join_node[i]][join_node[j + i + 1]] == 1:
                join_edge.append([join_node[i], join_node[j + i + 1]])
                d_edgey = map.virzuobiao[join_node[j + i + 1]][1] - map.virzuobiao[join_node[i]][1]
                d_edgex = map.virzuobiao[join_node[j + i + 1]][0] - map.virzuobiao[join_node[i]][0]
                length = d_edgey ** 2 + d_edgex ** 2
                length = length ** 0.5
                join_edge_length.append(length)
    edge_num = len(join_edge)
    # 计算所有转角
    join_angle = []
    for i in range(len(join_node)):
        temp_edges_oc = []
        for j in range(len(join_node)):
            if map.map[join_node[i]][join_node[j]] == 1:
                d_edgey = map.virzuobiao[join_node[j]][1] - map.virzuobiao[join_node[i]][1]
                d_edgex = map.virzuobiao[join_node[j]][0] - map.virzuobiao[join_node[i]][0]
                length = d_edgey ** 2 + d_edgex ** 2
                length = length ** 0.5
                if d_edgey >= 0:
                    now_angle = math.degrees(math.asin(d_edgey / length))
                else:
                    now_angle = math.degrees(math.asin(d_edgey / length)) + 180
                temp_edges_oc.append(now_angle)
        temp_edges_oc.sort()
        if len(temp_edges_oc) == 2:

            now_angle = abs(180 - temp_edges_oc[1] + temp_edges_oc[0])
            # print('2的情况', now_angle)
            join_angle.append(now_angle)
        elif len(temp_edges_oc) > 2:
            for angle_no in range(len(temp_edges_oc)):
                lixiang_angle = 360 / len(temp_edges_oc)
                if angle_no != 0:
                    now_angle = abs(lixiang_angle - temp_edges_oc[angle_no] + temp_edges_oc[angle_no - 1])
                else:
                    now_angle = abs(lixiang_angle - temp_edges_oc[angle_no - 1] + temp_edges_oc[angle_no])
                # print('3的情况', now_angle)
                join_angle.append(now_angle)

    #  计算交叉数
    coss_sum = 0
    jisuan = 0
    # 计算交叉数
    for i in range(edge_num):
        now_edge = [join_edge[i][0], join_edge[i][1]]
        jjj = 0
        jj = 0
        for j in range(edge_num - i - 1):
            jisuan = jisuan + 1
            other_edge = [join_edge[j + i + 1][0], join_edge[j + i + 1][1]]
            if set(now_edge) & set(other_edge):
                # 有公共点，判断是否共线
                one_edge = map.virzuobiao[now_edge[0]] - map.virzuobiao[now_edge[1]]
                two_edge = map.virzuobiao[other_edge[0]] - map.virzuobiao[other_edge[1]]
                if one_edge[0] / two_edge[0] == one_edge[1] / two_edge[1]:
                    if now_edge[0] == other_edge[0] or now_edge[1] == other_edge[1]:
                        if one_edge[0] * two_edge[0] > 0:
                            coss_sum = coss_sum + 1
                            # print('公共1', map.virzuobiao[now_edge[0]], map.virzuobiao[now_edge[1]], map.virzuobiao[other_edge[0]], map.virzuobiao[other_edge[1]])
                    else:
                        if one_edge[0] * two_edge[0] < 0:
                            coss_sum = coss_sum + 1
                            # print('公共2', map.virzuobiao[now_edge[0]], map.virzuobiao[now_edge[1]], map.virzuobiao[other_edge[0]], map.virzuobiao[other_edge[1]])
            else:
                # 矩阵检测
                jjj = jjj + 1
                if max([map.virzuobiao[now_edge[0]][0], map.virzuobiao[now_edge[1]][0]]) >= min(
                        [map.virzuobiao[other_edge[0]][0], map.virzuobiao[other_edge[1]][0]]) \
                        and min([map.virzuobiao[now_edge[0]][0], map.virzuobiao[now_edge[1]][0]]) <= max(
                    [map.virzuobiao[other_edge[0]][0], map.virzuobiao[other_edge[1]][0]]) \
                        and max([map.virzuobiao[now_edge[0]][1], map.virzuobiao[now_edge[1]][1]]) >= min(
                    [map.virzuobiao[other_edge[0]][1], map.virzuobiao[other_edge[1]][1]]) \
                        and min([map.virzuobiao[now_edge[0]][1], map.virzuobiao[now_edge[1]][1]]) <= max(
                    [map.virzuobiao[other_edge[0]][1], map.virzuobiao[other_edge[1]][1]]):
                    # 计算行列式 ，判断是否交叉
                    1
                    jj = jj + 1
                    one_one = map.virzuobiao[other_edge[0]] - map.virzuobiao[now_edge[0]]
                    one_two = map.virzuobiao[other_edge[1]] - map.virzuobiao[now_edge[0]]
                    ttwo = map.virzuobiao[now_edge[1]] - map.virzuobiao[now_edge[0]]
                    det_out = (one_one[0] * ttwo[1] - one_one[1] * ttwo[0]) * (
                            one_two[0] * ttwo[1] - one_two[1] * ttwo[0])
                    one_one2 = map.virzuobiao[now_edge[0]] - map.virzuobiao[other_edge[0]]
                    one_two2 = map.virzuobiao[now_edge[1]] - map.virzuobiao[other_edge[0]]
                    ttwo2 = map.virzuobiao[other_edge[1]] - map.virzuobiao[other_edge[0]]
                    det_out2 = (one_one2[0] * ttwo2[1] - one_one2[1] * ttwo2[0]) * (
                            one_two2[0] * ttwo2[1] - one_two2[1] * ttwo2[0])
                    if det_out <= 0 and det_out2 <= 0:
                        coss_sum = coss_sum + 1
                        # print('下面的', det_out)
                        # print('非公共', map.virzuobiao[now_edge[0]], map.virzuobiao[now_edge[1]], map.virzuobiao[other_edge[0]], map.virzuobiao[other_edge[1]])
        # print(jjj, jj)

    # 组成lossfunction
    ending_dic = {}
    ending_dic['coss_sum'] = coss_sum
    # print(jisuan, len(join_edge))
    # 计算边标准差
    # print(join_edge_length)
    join_edge_length = np.array(join_edge_length)
    edge_avg = np.sum(join_edge_length) / join_edge_length.shape[0]
    edge_std = np.std(join_edge_length)
    # 计算点的离散程度
    join_node_cood = np.array(join_node_cood)
    mid_x = (max(join_node_cood[:, 0]) + min(join_node_cood[:, 0])) / 2
    mid_y = (max(join_node_cood[:, 1]) + min(join_node_cood[:, 1])) / 2
    average_x = np.sum(join_node_cood[:, 0]) / join_node_cood.shape[0]
    average_y = np.sum(join_node_cood[:, 1]) / join_node_cood.shape[0]
    tupianmianji = [max(join_node_cood[:, 0]) - min(join_node_cood[:, 0]),
                    max(join_node_cood[:, 1]) - min(join_node_cood[:, 1])]
    dian_mess = [[mid_x, mid_y], [average_x, average_y]]
    x_bilv = abs(average_x - mid_x) / tupianmianji[0]
    y_bilv = abs(average_y - mid_y) / tupianmianji[1]
    node_mess = ((average_x - mid_x) ** 2 + (average_y - mid_y) ** 2) ** 0.5
    # 计算点的相关系数
    join_node_change = join_node_cood.T
    join_node_xianguanxishu = np.corrcoef(join_node_change)
    # 计算角的标准差
    join_angle = np.array(join_angle)
    angle_avg = np.sum(join_angle) / join_angle.shape[0]
    angle_std = np.std(join_angle)
    angle_std = (np.sum(join_angle ** 2) / join_angle.shape[0]) ** 0.5

    print('相关系数', join_node_xianguanxishu[0][1])
    return coss_sum, edge_std / edge_avg, edge_std, edge_avg, x_bilv, y_bilv, node_mess, tupianmianji, dian_mess, join_angle, angle_avg, angle_std


if __name__ == '__main__':
    1
